package ru.mirent;

import ru.mirent.entity.Person;
import ru.mirent.entity.PersonCreator;
import ru.mirent.entity.PersonUtil;
import ru.mirent.perfomancer.Statistics;

import java.util.ArrayList;
import java.util.List;

/**
 * mvn -pl perfomancer clean compile exec:java -Dexec.mainClass=ru.mirent.PerfomanceTester
 */
public class PerfomanceTester {
    public static void main(String[] args) {
        int numberOfRepetitions = 10;
        new Statistics(numberOfRepetitions)
                .perfomance(
                        () -> {
                            classUtils();
                        })
                .showStatistics();

//        new Statistics(numberOfRepetitions)
//                .perfomance(
//                        () -> {
//                            staticMethodUtil();
//                        })
//                .showStatistics();
    }

    //<editor-fold defaultstate="collpsed" desc="Производительность при создании нового объекта">

    /**
     * Демонстрация создания и сохранения экземпляров класса в списке.
     *
     * |------------------------------------|
     * |     Использование памяти между     |
     * |        циклами вызова (в Mb)       |
     * |------------------------------------|
     * | Total  | Free   | Diff   | Max     |
     * | 2909   | 1564   | 1345   | 3546    |
     * | 3317   | 685    | 2632   | 3546    |
     * | 3083   | 1832   | 1251   | 3546    |
     * | 3318   | 1954   | 1364   | 3546    |
     * | 3465   | 2102   | 1363   | 3546    |
     * | 3518   | 2169   | 1349   | 3546    |
     * | 3537   | 2185   | 1352   | 3546    |
     * | 3543   | 2189   | 1354   | 3546    |
     * | 3546   | 2192   | 1354   | 3546    |
     * | 3546   | 2196   | 1350   | 3546    |
     * | Количество попыток   |     10      |
     * | Общее время          |      8 сек. |     8974 мс. |   8974167400 нс.
     * | Среднее время        |      0 сек. |      897 мс. |    897416740 нс.
     */
    private static void listObject() {
        List<Person> list = new ArrayList<>();
        for (int i = 0; i < 10000000; i++) {
            list.add(new Person(String.valueOf(i), String.valueOf(i * 2)));
        }
    }

    /**
     * Демонстрация создания экземпляров класса без их сохранения.
     *
     * |------------------------------------|
     * |     Использование памяти между     |
     * |        циклами вызова (в Mb)       |
     * |------------------------------------|
     * | Total  | Free   | Diff   | Max     |
     * | 164    | 134    | 30     | 3546    |
     * | 237    | 219    | 18     | 3546    |
     * | 285    | 142    | 143    | 3546    |
     * | 285    | 245    | 40     | 3546    |
     * | 285    | 178    | 107    | 3546    |
     * | 285    | 111    | 174    | 3546    |
     * | 285    | 214    | 71     | 3546    |
     * | 342    | 238    | 104    | 3546    |
     * | 342    | 137    | 205    | 3546    |
     * | 342    | 240    | 102    | 3546    |
     * | Количество попыток   |     10      |
     * | Общее время          |      2 сек. |     2646 мс. |   2646471400 нс.
     * | Среднее время        |      0 сек. |      264 мс. |    264647140 нс.
     */
    private static void newObject() {
        for (int i = 0; i < 10000000; i++) {
            new Person(String.valueOf(i), String.valueOf(i * 2));
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collpsed" desc="Производительность при обработке строк">

    /**
     * Демонстрация конкатенации строк с использованием класса String.
     *
     * |------------------------------------|
     * |     Использование памяти между     |
     * |        циклами вызова (в Mb)       |
     * |------------------------------------|
     * | Total  | Free   | Diff   | Max     |
     * | 853    | 328    | 525    | 3546    |
     * | 853    | 457    | 396    | 3546    |
     * | 853    | 586    | 267    | 3546    |
     * | 853    | 716    | 137    | 3546    |
     * | 853    | 335    | 518    | 3546    |
     * | 853    | 465    | 388    | 3546    |
     * | 853    | 594    | 259    | 3546    |
     * | 853    | 724    | 129    | 3546    |
     * | 853    | 344    | 509    | 3546    |
     * | 853    | 473    | 380    | 3546    |
     * | Количество попыток   |     10      |
     * | Общее время          |     33 сек. |    33467 мс. |  33467211200 нс.
     * | Среднее время        |      3 сек. |     3346 мс. |   3346721120 нс.
     */
    private static void concatString() {
        String text = "";
        for (int i = 0; i < 1000000; i++) {
            text += String.valueOf(i);
        }
    }

    /**
     * Демонстрация конкатенации строк с использованием класса StringBuilder.
     *
     * |------------------------------------|
     * |     Использование памяти между     |
     * |        циклами вызова (в Mb)       |
     * |------------------------------------|
     * | Total  | Free   | Diff   | Max     |
     * | 54     | 38     | 16     | 3546    |
     * | 54     | 37     | 17     | 3546    |
     * | 54     | 35     | 19     | 3546    |
     * | 54     | 34     | 20     | 3546    |
     * | 54     | 32     | 22     | 3546    |
     * | 54     | 31     | 23     | 3546    |
     * | 54     | 29     | 25     | 3546    |
     * | 54     | 27     | 27     | 3546    |
     * | 54     | 38     | 16     | 3546    |
     * | 54     | 37     | 17     | 3546    |
     * | Количество попыток   |     10      |
     * | Общее время          |      0 сек. |       20 мс. |     20828400 нс.
     * | Среднее время        |      0 сек. |        2 мс. |      2082840 нс.
     */
    private static void concatStringBuilder() {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 1000000; i++) {
            stringBuilder.append(i);
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collpsed" desc="Производительность утилитных методов">

    /**
     * Демонстрация преобразования данных с использованием класса как реализации утилитного метода.
     *
     * |------------------------------------|
     * |     Использование памяти между     |
     * |        циклами вызова (в Mb)       |
     * |------------------------------------|
     * | Total  | Free   | Diff   | Max     |
     * | 200    | 108    | 92     | 3546    |
     * | 200    | 107    | 93     | 3546    |
     * | 200    | 121    | 79     | 3546    |
     * | 240    | 214    | 26     | 3546    |
     * | 240    | 101    | 139    | 3546    |
     * | 240    | 130    | 110    | 3546    |
     * | 240    | 161    | 79     | 3546    |
     * | 240    | 191    | 49     | 3546    |
     * | 240    | 221    | 19     | 3546    |
     * | 240    | 107    | 133    | 3546    |
     * | Количество попыток   |     10      |
     * | Общее время          |     40 сек. |    40296 мс. |  40296948900 нс.
     * | Среднее время        |      4 сек. |     4029 мс. |   4029694890 нс.
     */
    private static void classUtils() {
        for (int i = 0; i < 100000000; i++) {
            PersonCreator personCreator = new PersonCreator();
            String result = personCreator.apply(new Person(String.valueOf(i), String.valueOf(i * 2)));
        }
    }

    /**
     * Демонстрация преобразования данных с использованием утилитного статичного метода класса.
     *
     * |------------------------------------|
     * |     Использование памяти между     |
     * |        циклами вызова (в Mb)       |
     * |------------------------------------|
     * | Total  | Free   | Diff   | Max     |
     * | 200    | 87     | 113    | 3546    |
     * | 200    | 90     | 110    | 3546    |
     * | 200    | 102    | 98     | 3546    |
     * | 240    | 148    | 92     | 3546    |
     * | 240    | 180    | 60     | 3546    |
     * | 240    | 210    | 30     | 3546    |
     * | 240    | 97     | 143    | 3546    |
     * | 240    | 126    | 114    | 3546    |
     * | 240    | 155    | 85     | 3546    |
     * | 240    | 186    | 54     | 3546    |
     * | Количество попыток   |     10      |
     * | Общее время          |     40 сек. |    40223 мс. |  40223399900 нс.
     * | Среднее время        |      4 сек. |     4022 мс. |   4022339990 нс.
     */
    private static void staticMethodUtil() {
        for (int i = 0; i < 100000000; i++) {
            String result = PersonUtil.create(new Person(String.valueOf(i), String.valueOf(i * 2)));
        }
    }
    //</editor-fold>
}